<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Animation
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora048.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora050.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Animation</H2> The animation of graphics on a screen reuses
techniques of animated drawings. The major part of a drawing does
not change, only the animated part must modify the color of its
constituent pixels. One of the immediate problems we meet is the speed
of animation. It can vary depending on the computational complexity
and on the execution speed of the processor. Therefore, to be portable,
an application containing animated graphics must take into account the
speed of the processor. To get smooth rendering, it is advisable to
display the animated object at the new position, followed by the erasure
of the old one and taking special care with the intersection of the old
and new regions.<BR>
<BR>

<H5> Moving an object</H5>
We simplify the problem of moving an object by choosing objects of a
simple shape, namely rectangles. The remaining difficulty is knowing how
to redisplay the background of the screen once the object has been moved.<BR>
<BR>
We try to make a rectangle move around in a closed space. The object moves
at a certain speed in directions X and Y. When it encounters a border of
the graphical window, it bounces back depending on the angle of impact.
We assume a situation without overlapping of the new and old positions
of the object. The function <TT>calc_pv</TT> computes the new position
and the new velocity from an old position <TT>(</TT>x<CODE>,</CODE>y<TT>)</TT>, the size of
the object <TT>(</TT>sx<CODE>,</CODE>sy<TT>)</TT> and from the old speed <TT>(</TT>dx<CODE>,</CODE>dy<TT>)</TT>,
taking into account the borders of the window.


<PRE><BR># <B>let</B><CODE> </CODE>calc_pv<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><TT>(</TT>sx<CODE>,</CODE>sy<TT>)</TT><CODE> </CODE><TT>(</TT>dx<CODE>,</CODE>dy<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>nx1<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<CODE>+</CODE>dx<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE><CODE> </CODE>ny1<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<CODE> </CODE><CODE>+</CODE><CODE> </CODE>dy<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE>nx2<CODE> </CODE><CODE>=</CODE><CODE> </CODE>x<CODE>+</CODE>sx<CODE>+</CODE>dx<CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE><CODE> </CODE>ny2<CODE> </CODE><CODE>=</CODE><CODE> </CODE>y<CODE>+</CODE>sy<CODE>+</CODE>dy<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE>ndx<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE>dx<CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE><CODE> </CODE>ndy<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE>dy<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>nx1<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE><CODE>||</CODE><CODE> </CODE><TT>(</TT>nx2<CODE> </CODE><CODE>&gt;=</CODE><CODE> </CODE>Graphics.size_x()<TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE>ndx<CODE> </CODE><CODE>:=</CODE><CODE> </CODE><CODE>-</CODE>dx<CODE> </CODE><TT>)</TT>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>ny1<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE><CODE>||</CODE><CODE> </CODE><TT>(</TT>ny2<CODE> </CODE><CODE>&gt;=</CODE><CODE> </CODE>Graphics.size_y()<TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE>ndy<CODE> </CODE><CODE>:=</CODE><CODE> </CODE><CODE>-</CODE>dy<CODE> </CODE><TT>)</TT>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><TT>(</TT>x<CODE>+</CODE><CODE> </CODE><CODE>!</CODE>ndx<CODE>,</CODE><CODE> </CODE>y<CODE>+</CODE><CODE> </CODE><CODE>!</CODE>ndy<TT>)</TT><CODE>,</CODE><CODE> </CODE><TT>(</TT><CODE>!</CODE>ndx<CODE>,</CODE><CODE> </CODE><CODE>!</CODE>ndy<TT>)</TT><TT>)</TT>;;<BR><CODE>val calc_pv :</CODE><BR><CODE>  int * int -&gt; int * int -&gt; int * int -&gt; (int * int) * (int * int) = &lt;fun&gt;</CODE><BR>

</PRE>

The function <TT>move_rect</TT> moves the rectangle given by <TT>pos</TT>
and <TT>size</TT> <TT>n</TT> times, the trajectory being indicated by
its <TT>speed</TT> and by taking into account the borders of the space.
The trace of movement which one can see in figure <A HREF="book-ora049.html#fig-anim">5.7</A> is
obtained by inversion of the corresponding bitmap of the displaced
rectangle.


<PRE><BR># <B>let</B><CODE> </CODE>move_rect<CODE> </CODE>pos<CODE> </CODE>size<CODE> </CODE>speed<CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE><CODE> </CODE>y<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>pos<CODE> </CODE><B>and</B><CODE> </CODE><TT>(</TT>sx<CODE>,</CODE>sy<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>size<CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>mem<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><TT>(</TT>Graphics.get_image<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>sx<CODE> </CODE>sy<TT>)</TT><CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><B>rec</B><CODE> </CODE>move_aux<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>speed<CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE>Graphics.moveto<CODE> </CODE>x<CODE> </CODE>y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT><TT>(</TT>nx<CODE>,</CODE>ny<TT>)</TT><CODE>,</CODE>n_speed<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>calc_pv<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><TT>(</TT>sx<CODE>,</CODE>sy<TT>)</TT><CODE> </CODE>speed<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>and</B><CODE> </CODE>old_mem<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>!</CODE>mem<CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>mem<CODE> </CODE><CODE>:=</CODE><CODE> </CODE>Graphics.get_image<CODE> </CODE>nx<CODE> </CODE>ny<CODE> </CODE>sx<CODE> </CODE>sy;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>Graphics.blue;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE>nx<CODE> </CODE>ny<CODE> </CODE>sx<CODE> </CODE>sy;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.draw_image<CODE> </CODE><TT>(</TT>inv_image<CODE> </CODE>old_mem<TT>)</TT><CODE> </CODE>x<CODE> </CODE>y;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>move_aux<CODE> </CODE>nx<CODE> </CODE>ny<CODE> </CODE>n_speed<CODE> </CODE><TT>(</TT>n<CODE>-</CODE><CODE>1</CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>move_aux<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>speed<CODE> </CODE>n;;<BR><CODE>val move_rect : int * int -&gt; int * int -&gt; int * int -&gt; int -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The following code corresponds to the drawings in figure <A HREF="book-ora049.html#fig-anim">5.7</A>.
The first is obtained on a uniformly red background, the second by moving
the rectangle across the image of Jussieu.<BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>anim_rect<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.moveto<CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE>5</CODE><CODE> </CODE><CODE>1</CODE><CODE>2</CODE><CODE>0</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>Graphics.white;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.draw_string<CODE> </CODE><CODE>"Start"</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>move_rect<CODE> </CODE><TT>(</TT><CODE>1</CODE><CODE>4</CODE><CODE>0</CODE><CODE>,</CODE><CODE>1</CODE><CODE>2</CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE><TT>(</TT><CODE>8</CODE><CODE>,</CODE><CODE>8</CODE><TT>)</TT><CODE> </CODE><TT>(</TT><CODE>8</CODE><CODE>,</CODE><CODE>4</CODE><TT>)</TT><CODE> </CODE><CODE>1</CODE><CODE>5</CODE><CODE>0</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>Graphics.current_point()<CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.moveto<CODE> </CODE><TT>(</TT>x<CODE>+</CODE><CODE>1</CODE><CODE>3</CODE><TT>)</TT><CODE> </CODE>y;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>Graphics.white;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.draw_string<CODE> </CODE><CODE>"End"</CODE>;;<BR><CODE>val anim_rect : unit -&gt; unit = &lt;fun&gt;</CODE><BR># anim_rect();;<BR><CODE>- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1>
<TR><TD  ALIGN=center NOWRAP><IMG SRC="book-ora015.gif"></TD>
<TD  ALIGN=center NOWRAP><IMG SRC="book-ora016.gif"></TD>
</TR></TABLE>
</DIV>
<BR>
<DIV ALIGN=center>Figure 5.7: Moving an object.</DIV><BR>

<A NAME="fig-anim"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>
The problem was simplified, because there was no intersection between two
successive positions of the moved object. If this is not the case, it is
necessary to write a function that computes this intersection, which can
be more or less complicated depending on the form of the object. In the
case of a square, the intersection of two squares yields a rectangle.
This intersection has to be removed.<BR>
<BR>
<HR>
<A HREF="book-ora048.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora050.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
